﻿using System;
using System.Linq;
using System.Xml;
using System.Net;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Unity;
using DXTools.UI.Core;
using DXTools.UI.Modules.Configuration.Views;
using DXTools.UI.Core.Events;
using System.Collections.Generic;
using DXTools.UI.Core.ViewModel;
using System.Collections.ObjectModel;
using System.Text;
using DXTools.UI.Core.DataProviders;
using DXTools.Core.CrmSdk;
using DXTools.UI.Core.Model;
using DXTools.Core.Model;
using DXTools.Core.Enum;
using DXTools.UI.Modules.Configuration.Model;
using DXTools.UI.Modules.Configuration.Events;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Xml.Schema;


namespace DXTools.UI.Modules.Configuration.ViewModels
{
    public class SitemapViewModel : ViewModelBase
    {
        #region Private Attributes
        private const string HEADER_INFO = "Sitemap Options";
        private ICRMDataProvider crmDataProvider;
        #endregion

        #region Delegate Commands
        public DelegateCommand<object> AddNavItemCommand { get; private set; }
        public DelegateCommand<object> RemoveNavItemCommand { get; private set; }
        #endregion

        #region Properties

        private String _sitemapXml;

        private Entity _sitemap;
        public Entity Sitemap
        {
            get
            {
                return _sitemap;
            }
            set
            {
                _sitemap = value;
                RaisePropertyChanged("Sitemap");
            }
        }
        private bool _navItemExists;
        public bool NavItemExists
        {
            get
            {
                return _navItemExists;
            }
            set
            {
                _navItemExists = value;
                RaisePropertyChanged("NavItemExists");
            }
        }

        
        #endregion

        #region Constructors

        public SitemapViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer container)
            :base(regionManager,eventAggregator,container)
        {
            this.HeaderInfo = HEADER_INFO;

            this.CloseViewCommand = new DelegateCommand<object>(this.CloseView, this.CanCloseView);

            this.AddNavItemCommand = new DelegateCommand<object>(this.AddNavItem, this.CanAddNavItem);
            this.RemoveNavItemCommand = new DelegateCommand<object>(this.RemoveNavItem, this.CanRemoveNavItem);
            
            //this.SearchCommand = new DelegateCommand<object>(this.Search, this.CanSearch);

            crmDataProvider = new CRMDataProvider();

            this.RetrieveSiteMap();

            

            




        }

        #endregion

        #region Command Buttons

        private void AddNavItem(object commandArg)
        {
            AddSiteMapNavItem();
        }
        private bool CanAddNavItem(object commandArg)
         {
             return !NavItemExists;
         }

        private void RemoveNavItem(object commandArg)
        {
            RemoveSiteMapNavItem();
        }
        private bool CanRemoveNavItem(object commandArg)
        {
            return NavItemExists;
        }   

        #endregion

         #region Close

         private void CloseView(object commandArg)
         {
             base.CloseView();
         }
         private bool CanCloseView(object commandArg)
         {
             return true;
         }

         #endregion

        #region Methods

         private void RetrieveSiteMap()
         {
             AsyncCallback asyncCallback = (result =>
             {
                 IOrganizationService service = (IOrganizationService)result.AsyncState;

                 EntityCollection response = service.EndRetrieveMultiple(result);
                 ObservableCollection<Item> sitemaps = new ObservableCollection<Item>();
                 Action method = () =>
                 {
                     if (response.Entities.Count > 0)
                     {
                         _sitemap = response.Entities[0];

                         _sitemapXml = Convert.ToString(_sitemap["sitemapxml"]);

                         // Update nav item exists property
                         XDocument doc = XDocument.Parse(_sitemapXml);
                         NavItemExists =  (doc.XPathSelectElement("//Group[@Id='dxtools_Group']") != null);
                         
                         AddNavItemCommand.RaiseCanExecuteChanged();
                         RemoveNavItemCommand.RaiseCanExecuteChanged();
                     }

                     this.IsBusy = false;
                 };

                 this.View.Dispatcher.BeginInvoke(method);

             });

             this.IsBusy = true;

             this.crmDataProvider.RetrieveSitemap(asyncCallback);
         }

         private void AddSiteMapNavItem()
         {
             AsyncCallback asyncCallback = (result =>
             {
                 IOrganizationService service = (IOrganizationService)result.AsyncState;

                 service.EndUpdate(result);
              
                 Action method = () =>
                 {

                    // Now publish the sitemap
                    AsyncCallback asyncCallbackPublish = (resultPublish =>
                    {
                        IOrganizationService servicePublish = (IOrganizationService)resultPublish.AsyncState;

                        OrganizationResponse responsePublish = servicePublish.EndExecute(resultPublish);

                         Action methodPublish = () =>
                         {
                             RetrieveSiteMap();
                         };

                         this.View.Dispatcher.BeginInvoke(methodPublish);
                    });
                    
                     this.crmDataProvider.PublishSitemap(asyncCallbackPublish);


                     
                 };

                 this.View.Dispatcher.BeginInvoke(method);

             });

            

             if (!NavItemExists)
             {
                 this.IsBusy = true;

                 // Update nav item exists property
                 XDocument doc = XDocument.Parse(_sitemapXml);

                 XElement areaNode = doc.XPathSelectElement("//Area[@Id='Settings']");
                 if (areaNode != null)
                 {
                     XElement dxToolsNode = XElement.Parse("<Group Id=\"dxtools_Group\"><Titles><Title LCID=\"1033\" Title=\"Dynamics XRM Tools\" /></Titles><SubArea Id=\"dxtools_UIShell\" Icon=\"$webresource:dxtools_/images/dxtools18x18.png\" Url=\"$webresource:dxtools_/SL/ShellLoader.htm\"><Titles><Title LCID=\"1033\" Title=\"Start\" /></Titles></SubArea></Group>", LoadOptions.None);
                     areaNode.Add(dxToolsNode);

                     _sitemapXml = doc.ToString();
                        
                     _sitemap["sitemapxml"] = _sitemapXml;

                     this.crmDataProvider.UpdateEntity(_sitemap, asyncCallback);
                 }

             }

         }

         private void RemoveSiteMapNavItem()
         {
             AsyncCallback asyncCallback = (result =>
             {
                 IOrganizationService service = (IOrganizationService)result.AsyncState;

                 service.EndUpdate(result);

                 Action method = () =>
                 {

                     // Now publish the sitemap
                     AsyncCallback asyncCallbackPublish = (resultPublish =>
                     {
                         IOrganizationService servicePublish = (IOrganizationService)resultPublish.AsyncState;

                         OrganizationResponse responsePublish = servicePublish.EndExecute(resultPublish);

                         Action methodPublish = () =>
                         {
                             RetrieveSiteMap();
                         };

                         this.View.Dispatcher.BeginInvoke(methodPublish);
                     });

                     this.crmDataProvider.PublishSitemap(asyncCallbackPublish);


                 };

                 this.View.Dispatcher.BeginInvoke(method);

             });


             if (NavItemExists)
             {
                 this.IsBusy = true;
                 // Update nav item exists property
                 XDocument doc = XDocument.Parse(_sitemapXml);

                 XElement groupNode = doc.XPathSelectElement("//Group[@Id='dxtools_Group']");
                 if (groupNode != null)
                 {
                     groupNode.Remove();
                       
                     _sitemapXml = doc.ToString();
                                         
                     _sitemap["sitemapxml"] = _sitemapXml;

                     this.crmDataProvider.UpdateEntity(_sitemap, asyncCallback);
                 }

             }

         }

        #endregion
    }
}
